<?php
declare(strict_types=1);

namespace App\Tool;

class SensitiveFilter
{
    private $sensitiveWords;
    private $pattern;

    public function __construct(array $words)
    {
        $this->sensitiveWords = array_map('preg_quote', $words);
        $this->pattern = '/(' . implode('|', $this->sensitiveWords) . ')/u';
    }

    public function check($text): array
    {
        $matches = [];

        $hasMatch = preg_match_all($this->pattern, $text, $matches, PREG_OFFSET_CAPTURE);

        return [
            'hasSensitive' => $hasMatch > 0,
            'matches' => $matches[1] ?? [],
            'markedText' => $this->markText($text),
        ];
    }

    private function markText(string $text): string
    {
        return preg_replace_callback($this->pattern, function($matches) {
            return '<span class="sensitive-word" data-original="' .
                htmlspecialchars($matches[0]) . '">' .
                htmlspecialchars($matches[0]) . '</span>';
        }, $text);
    }

    public function analyzeText(string $text)
    {
        $result = $this->check($text);

        return [
            'original_text' => $text,
            'has_sensitive' => $result['hasSensitive'],
            'sensitive_positions' => $this->getSensitivePositions($text),
            'marked_html' => $result['markedText'],
            'sensitive_words' => array_unique($result['matches'])
        ];
    }

    private function getSensitivePositions($text): array
    {
        $positions = [];
        foreach ($this->sensitiveWords as $word) {
            $offset = 0;
            while (($pos = mb_strpos($text, $word, $offset, 'UTF-8')) !== false) {
                $positions[] = [
                    'word' => $word,
                    'start' => $pos,
                    'end' => $pos + mb_strlen($word, 'UTF-8') - 1,
                    'length' => mb_strlen($word, 'UTF-8')
                ];
                $offset = $pos + 1;
            }
        }
        return $positions;
    }
}